var User = require('./models').User;
var Promise = require('bluebird');
var crypto = require('crypto');
var config = require('./config');

var RANDOM_LEN = 10;

var _genRandomString = function(callback) {
  crypto.randomBytes(RANDOM_LEN, (err, buf) => {
    if (err) return callback(err);
    return callback(null, buf.toString('base64'));
  });
};

/**
 * [_genUserKey generate encrypted user key]
 * @param  {integer} user id
 * @param  {Function} callback(err, key)  
 */
var _genUserKey = function(id, callback) {
  var cipher = crypto.createCipher('aes192', config.aeskey);
  _genRandomString(function(err, str) {
    if (err) {
      return callback && callback(err);
    }
    var encrypted = cipher.update(id + '/' + str, 'utf8', 'hex');
    encrypted += cipher.final('hex');
    return callback && callback(null, encrypted);
  });

}

/**
 * [_decodeUserKey decode user id from user key]
 * @param  {string} key [the encrypted user key]
 * @return {integer}     [user id]
 */
var _decodeUserKey = function(key) {
  var decipher = crypto.createDecipher('aes192', config.aeskey);

  var encrypted = key;
  var decrypted = decipher.update(encrypted, 'hex', 'utf8');
  decrypted += decipher.final('utf8');
  return parseInt(decrypted.split('/')[0]);
}

/**
 * [initUser init user by id, will create a new user if not exist.]
 * @param  {integer} id [user id]
 * @return {Promise}    [Promise with user object]
 */
var initUser = function(id) {
  return new Promise(function(resolve, reject) {
    _genUserKey(id, function(err, key) {
      if (err) {
        return reject(err);
      }
      User
        .findOrCreate({
          where: {
            id: parseInt(id)
          },
          defaults: {
            userkey: key
          }
        })
        .spread(function(user, created) {
          return resolve(user);
        }).catch(function(err) {
          return reject(err);
        });
    });
  });
};

/**
 * [validateUserKey validate a user key]
 * @param  {string} key [user key]
 * @return {Promise}     [Promise with user object]
 */
var validateUserKey = function(key) {
  var id = _decodeUserKey(key);
  return new Promise(function(resolve, reject) {
    User
      .findById(id)
      .then(function(user) {
        if (user.userkey == key) {
          resolve(user);
        } else {
          reject(new Error('invalid user key'));
        }
      }).catch(function(err) {
        reject(err);
      });
  });
}

exports.initUser = initUser;
exports.validateUserKey = validateUserKey;